package org.ninjarope.cinderstained.main.gameplay.definition;

import java.util.HashMap;

import org.ninjarope.cinderstained.main.engine.Game;
import org.ninjarope.cinderstained.main.gameplay.definition.damage.Damage;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;

public abstract class GameActor implements Comparable<GameActor> {
	protected final HashMap<String, Integer> stats = new HashMap<String, Integer>();
	public final Vector2 position;
	public final Rectangle bounds;
	private Texture tile;
	private TextureRegion reg;

	protected String atlas;
	protected String textureRegion;

	public GameActor() {
		position = new Vector2();
		bounds = new Rectangle();
	}

	public void render(SpriteBatch batch) {
		batch.draw(tile, this.bounds.x, this.bounds.y, reg.getRegionX(),
				reg.getRegionY(), reg.getRegionWidth(), reg.getRegionHeight());
	}

	public void define(String sname) {
		String[] name = sname.split(":");
		atlas = name[0];
		textureRegion = name[1];

		reg = Game.get().getFromAtlas(atlas, textureRegion);
		tile = reg.getTexture();
		init(0, 0, reg.getRegionWidth(), reg.getRegionHeight());
	}

	public void init(float x, float y, float width, float height) {
		position.x = x;
		position.y = y;
		bounds.x = x - width / 2;
		bounds.y = y;
		bounds.width = width;
		bounds.height = height;
	}

	public void moveTo(Vector2 v) {
		this.bounds.x = v.x - this.bounds.width / 2;
		this.bounds.y = v.y;
		this.position.x = v.x;
		this.position.y = v.y;
	}

	public void moveTo(float x, float y) {
		this.bounds.x = x - this.bounds.width / 2;
		this.bounds.y = y;
		this.position.x = x;
		this.position.y = y;
	}

	public void move(float dx, float dy) {
		this.bounds.x += dx;
		this.position.x += dx;
		this.bounds.y += dy;
		this.position.y += dy;
	}

	public void inc(String s, int v) {
		if (stats.containsKey(s)) {
			stats.put(s, stats.get(s) + v);
		} else {
			stats.put(s, v);
		}
	}

	public void dec(String s, int v) {
		if (stats.containsKey(s)) {
			stats.put(s, stats.get(s) - v);
		} else {
			stats.put(s, -v);
		}
	}

	public void inc(String s) {
		this.inc(s, 1);
	}

	public void dec(String s) {
		this.dec(s, 1);
	}

	public int get(String s) {
		if (stats.containsKey(s)) {
			return stats.get(s);
		} else
			return 0;
	}

	public void set(String s) {
		stats.put(s, 1);
	}

	public void set(String s, int v) {
		stats.put(s, v);
	}

	public abstract void onBirth();

	public abstract void onTakeDamage(GameActor[] attacker);

	public abstract void onAttack(Damage dmg);

	public abstract void onWalk(GameTerrain terrain);

	// counts frames
	public abstract void onTick();

	// counts passed fields (multiple frames)
	public abstract void onStep();

	/**
	 * Method for performing action on creep death and performing
	 * transformations if needed
	 * 
	 * @return true if creep has died, false if creep has transformed
	 */
	public abstract boolean onDeath();

	@Override
	public int compareTo(GameActor o) {
		// compares using y cordinates and if they are equal using x cordiante
		if ((this.position.y > o.position.y)
				|| ((this.position.y == o.position.y) && (this.position.x < o.position.x))) {
			return -1;
		} else if ((this.position.y < o.position.y)
				|| ((this.position.y == o.position.y) && (this.position.x > o.position.x))) {
			return 1;
		} else
			return 0;
	}
}
